#include <cstring>
#include <cmath>
#include <iostream>  //预处理器指令 a PREPROCESSOR directive
using namespace std; // 使定义可见   make definitions visible
#include <vector>
#include <array>
#include <new>
#include <valarray>


/*  

    = valarray类
    = 类组合

    使用valarray类来声明一个对象时，需要在标识符valarray后面加上一对尖括号，并在其中包含所需的数据类型

    ●operator[](): 让您能够访问各个元素。
    ●size(): 返回包含的元素数。
    ●sum(): 返回所有元素的总和。
    ●max(): 返回最大的元素。
    ●min(): 返回最小的元素。

    valarray 的使用说明 - 见useValarray()

*/

class Student
{   
private:
    typedef std::valarray<double> ArrayDb;
    std::string name;       // contained object
    ArrayDb scores;         // contained object
    // private method for scores output
    std::ostream & arr_out(std::ostream & os) const;
    
public:
    Student() : name("Null Student"), scores() {}

    //名字
    explicit Student(const std::string & s)
        : name(s), scores() {}

    //数组长度
    explicit Student(int n) : name("Nully"), scores(n) {}

    //名称 + 数组长度
    Student(const std::string & s, int n)
        : name(s), scores(n) {}

    //名称 + 数组
    Student(const std::string & s, const ArrayDb & a)
        : name(s), scores(a) {}

    //scores(pd, n)  调用valarray 的构造函数
    //名称 + 数组默认值 + 数组长度 
    Student(const char * str, const double * pd, int n)
        : name(str), scores(pd, n) {}

    ~Student() {}

    //平均
    double Average() const;

    const std::string & Name() const;

    double & operator[](int i);

    double operator[](int i) const;

    // friends
    // input
    friend std::istream & operator>>(std::istream & is,
                                     Student & stu);  // 1 word
    friend std::istream & getline(std::istream & is,
                                  Student & stu);     // 1 line
    // output
    friend std::ostream & operator<<(std::ostream & os,
                                     const Student & stu);
};

//public methods
double Student::Average() const
{
    if (scores.size() > 0)
        return scores.sum()/scores.size();  
    else
        return 0;
}

const string & Student::Name() const
{
    return name;
}

double & Student::operator[](int i)
{
    return scores[i];         // use valarray<double>::operator[]()
}

double Student::operator[](int i) const
{
    return scores[i];
}

// private method
ostream & Student::arr_out(ostream & os) const
{
    int i;
    int lim = scores.size();
    if (lim > 0)
    {
        for (i = 0; i < lim; i++)
        {
            os << scores[i] << " ";
            if (i % 5 == 4)
                os << endl;
        }
        if (i % 5 != 0)
            os << endl;
    }
    else
        os << " empty array ";
    return os; 
}

// friends

// use string version of operator>>()
istream & operator>>(istream & is, Student & stu)
{
    is >> stu.name;
    return is; 
}

// 调用方式 getline(cin,stu1); 
// use string friend getline(ostream &, const string &)
istream & getline(istream & is, Student & stu)
{
    getline(is, stu.name);
    return is;
}

// use string version of operator<<()
ostream & operator<<(ostream & os, const Student & stu)
{
    os << "Scores for " << stu.name << ":\n";
    stu.arr_out(os);  // use private method for scores
    return os;
}


int main()
{

double gpa[5]={3.1,3.5,3.8,2.9,3.3};
Student stu1 = Student("小明",10);
stu1[0] = 10;
stu1[1] = 20;
stu1[3] = 20;
stu1[4] = 20;
cout << stu1 << endl;

cout << stu1.Average() << endl;

}

//valarray 的使用说明
void useValarray(){

    double gpa[5]={3.1,3.5,3.8,2.9,3.3};

    valarray<double> v1;//an array of double,size 0

    valarray<int> v2(8);//an array of 8 int elements

    //一个由8个int元素组成的数组，每个元素设置为10
    //an array of 8 int elements, each set to 10
    valarray<int> v3(10,8);

    //an array of 4 elements,initialized to the first 4 elements of gpa
    //一个由4个元素组成的数组，初始化为gpa的前4个元素
    valarray<double> v4(gpa,4);

}